# 对于@staticmethod
# @classmethod方法
# 茅塞顿开https://zhuanlan.zhihu.com/p/28010894
# class A(object):
#     a = 'a'
#     @staticmethod
#     def foo1(name):
#         print('hello', name, A.a)
#     #这里不能用self.a,要A.a
#     def foo2(self, name):
#         print('hello', name, self.a)
#     @classmethod
#     def foo3(cls, name):
#         print('hello', name, cls.a)
# class B(A):
#     a = 'b'
#     @staticmethod
#     def foo1(name):
#         print('hello', name, B.a)
#     def foo2(self, name):
#         print('subclass B')
#         print('hello', name, self.a)
#     @classmethod
#     def foo3(cls, name):
#         print('subclass B')
#         print('hello', name, cls.a)
#
#
# a = A()
# b = B()

# foo1和是类里面的一个静态方法，跟普通函数没什么区别，与类和实例都没有所谓的绑定关系，它只不过是碰巧存在类中的一个函数而已。不论是通过类还是实例都可以引用该方法。
# a.foo1("小熊猫") # hello 小熊猫 a
# A.foo1("小熊猫") # hello 小熊猫 a
# 有@staticmethod可以不用实例化对象A,直接用
# b.foo1("小熊猫") # subclass B， hello 大熊猫 b
# B.foo1("大熊猫") # subclass B， hello 大熊猫 b


# self可以自己定义
# 强制用某个类中的函数，但其他的用某个子类的
# a.foo2("小熊猫") # hello 小熊猫 a
# A.foo2("小熊猫") # hello 小熊猫 a   #error
# 正常的函数foo2一定要实例化类型A
# A.foo2(a, "小熊猫") # hello 小熊猫 a
# A.foo2(b, "小熊猫") # hello 小熊猫 b
# 不实例化用A类的函数，要传入具体的对象(相当于还是要实例化)
# A.foo2(A, "小熊猫") # hello 小熊猫 a
# A.foo2(B, "小熊猫") # hello 小熊猫 b
# 虽然传入的是B，但foo2用的是A类的，但类变量a用的是B类的
# B.foo2(a, "小熊猫") # subclass B， hello 小熊猫 a
# 虽然传入的是a，但foo2用的是B类的，但类变量a用的是a类的
# b.foo2("小熊猫") # subclass B， hello 小熊猫 b


# 这个没有体现@classmethod的精髓，classmethod也可以不用实例化
# 不会出现用B类函数，但用A类变量的情况？
# cls就是类（或子类）本身(就是xx) xx.()
# 前面self可以是好几种类 (是yy)xx.(yy,...)
# a.foo3("小熊猫")
# A.foo3("小熊猫")
# # a.foo3(a, "小熊猫") # TypeError: foo3() takes 2 positional arguments but 3 were given
# # A.foo3(A, "小熊猫") # TypeError: foo3() takes 2 positional arguments but 3 were given
# b.foo3("大熊猫")
# B.foo3("大熊猫")



# class A(object):
#     a = 'a'
#     @staticmethod
#     def foo1(name):
#         print('hello foo1', name, A.a)
#         print("hello foo4 ", B.foo2(B, "小熊猫"))
#     def foo2(self, name):
#         print('hello foo2', name, self.a)
#     @classmethod
#     def foo3(cls, name):
#         print('hello foo3', name, cls.a)
#         #print("hello foo5", cls.foo2(name))  #这个会报错foo2一定要实例化
#         print("hello foo5", cls().foo2(name))#调用A类的foo2
#         print("hello foo6", cls.foo1(name))#调用A类的foo1
# class B(A):
#     a = 'b'
#     @staticmethod
#     def foo1(name):
#         print('subclass B， hello', name, B.a)
#     def foo2(self, name):
#         print('subclass B， hello', name, self.a)
#     @classmethod
#     def foo3(cls, name):
#         print('subclass B， hello', name, cls.a)
#
# a = A()
# # a.foo1("小熊猫")
# a.foo3("小熊猫")
#
#
#
# class A(object):
#     @classmethod
#     def acquire(cls, param):
#         if cls is A:
#             raise Exception("只有子类才能调用！！！")
#         return "类 a %r 的参数为 %r" % (cls, param)
#
# class B(A):
#     pass
#
# class C(A):
#     pass
#
# print(B.acquire("小熊猫"))
# print(C.acquire("大熊猫"))
# print(A.acquire("爱吃竹子"))


# class A(object):
#     def m1(self, n):
#         print("self:", self)
#
#     @classmethod
#     def m2(cls, n):
#         print("cls:", cls)
#
#     @staticmethod
#     def m3(n):
#         pass
#
# a = A()
# print(A.m1)
# print(a.m1)




